package cn.gx.kevin.controller;

import cn.gx.kevin.domain.DynamicCountParam;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.serializer.*;
import cn.gx.kevin.common.annotation.NewOldCompare;
import cn.gx.kevin.common.bootenv.SpringContextUtil;
import cn.gx.kevin.common.thread.OperatorDataHolder;
import cn.gx.kevin.common.ui.*;
import cn.gx.kevin.common.user.ILoginUserContext;
import cn.gx.kevin.common.user.LoginUser;
import cn.gx.kevin.common.user.UserFunc;
import cn.gx.kevin.common.utils.*;
import cn.gx.kevin.service.IBaseService;

import org.apache.commons.beanutils.ConvertUtils;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.lang.reflect.*;
import java.net.URLDecoder;
import java.util.*;
import java.util.Map.Entry;

/**
 * controller 基类封装， 封装一些通用的请求处理逻辑，但不声明为web接口，需要子类根据需求重写声明
 *
 * @author kevin.huang
 * @date 2019/01/18
 */
public abstract class ResetfulBaseController<T extends Serializable, K extends Serializable>
        implements IControlCommon<T>, IServiceValid {

    public final Logger logger = org.slf4j.LoggerFactory.getLogger(getClass());
    protected IBaseService<T, K> service;
    private Method getIdMethod = null;
    protected Class<T> entityClass;
    protected String entityPath;
    protected Class<K> idClass;
    protected static String dateTimeFormat = "yyyy-MM-dd HH:mm:ss";

    protected SerializeConfig dateTimeSerialize = new SerializeConfig();
    protected String controllerSimpleName;

    private Map<String, LanguageMap> languageMap = LanguageStore.getLanguageStore();


    /**
     * 登陆用户的上下文
     ***/
    private ILoginUserContext loginUserCtx = null;

    public ILoginUserContext getLoginUserCtx() {
        if (this.loginUserCtx == null) {
            Object bean = getBean("loginUserCtx");
            if (bean != null) {
                this.loginUserCtx = (ILoginUserContext) bean;
            }
        }
        return loginUserCtx;
    }

    /**
     * 构造器，提取泛型class，实体bean名称
     */
    @SuppressWarnings("unchecked")
    public ResetfulBaseController() {
        controllerSimpleName = this.getClass().getSimpleName();
        Type type = getClass().getGenericSuperclass();
        if (type instanceof ParameterizedType) {
            ParameterizedType parameterizedType = (ParameterizedType) type;
            this.entityClass = (Class<T>) parameterizedType.getActualTypeArguments()[0];
            this.idClass = (Class<K>) parameterizedType.getActualTypeArguments()[1];
            String simpleName = this.entityClass.getSimpleName();
            entityPath = simpleName.substring(0, 1).toLowerCase() + simpleName.substring(1) + "/";
        }
        dateTimeSerialize.put(Date.class, new SimpleDateFormatSerializer(dateTimeFormat));
    }

    /**
     * 必须在子类中实现，并通过spring注入对应的service给this.service
     *
     * @param service
     */
    public abstract void setService(IBaseService<T, K> service);

    /**
     * 负责接收页面请求，反应对应的页面
     *
     * @param pageName-页面名称
     * @param request
     * @return
     * @throws Exception
     */
    public String page(String pageName, HttpServletRequest request) throws Exception {
        String pageModelPath = setPageModelPath(request);
        String pagePath = pageName;
        if (!"".equals(pageModelPath)) {
            pagePath = pageModelPath + pageName;
        }
        DataGrid dg = getDataGridCfg(request);
        if (dg == null) {
            request.setAttribute("dataGridJson", "{}");
        } else {
            try {
                JSONObject dgJson = JSONObject.parseObject(dg.toJson(request, (IControlCommon) this));
                request.setAttribute("dataGridJson", dgJson);
            } catch (Throwable e) {
                logger.error("{}", e);
            }
        }
        setUpdateObjectJson(request);
        onRequestPage(pageName, request);
        return pagePath;
    }

    /**
     * 页面返回前处理
     *
     * @param pageName
     * @param request
     * @throws Exception
     */
    protected void onRequestPage(String pageName, HttpServletRequest request) throws Exception {

    }

    /**
     * AJAX新增处理
     */
    public AjaxResult add(HttpServletRequest request) throws Exception {
        T t = AdminControllerHelper.getObjectFromRequest(getLoginUser(), request, entityClass, idClass, false);
        String filterResult = saveFilter(t, false, request);
        if ("".equals(filterResult)) {
            try {
                service.insertNotNull(t);
                this.onSaveAfter(true, t);
                return returnSuccData(getLang("common_saveSucess"), t);
            } catch (Exception ex) {
                logger.error("{}", ex);
                return returnFailData(getLang("common_saveFail"));
            }
        } else {
            return returnFailData(filterResult);
        }
    }

    /**
     * 更新接口
     *
     * @param request
     * @return
     * @throws Exception
     */
    public AjaxResult update(HttpServletRequest request) throws Exception {
        T t = AdminControllerHelper.getObjectFromRequest(getLoginUser(), request, entityClass, idClass, true);
        String filterResult = saveFilter(t, true, request);
        if ("".equals(filterResult)) {
            try {
                service.update(t);
                this.onSaveAfter(false, t);
                return returnSuccData(getLang("common_updateSucess"), t);
            } catch (Exception ex) {
                logger.error("{}", ex);
                return returnFailData(getLang("common_updateFail"));
            }
        } else {
            return returnFailData(filterResult);
        }
    }

    /**
     * 当新增，更新成功后调用，可用于设置操作日志 OperatorDataHolder.setDataObject(t);
     *
     * @param isUpdate
     * @param bean
     */
    protected void onSaveAfter(boolean isUpdate, T bean) {

    }

    /**
     * delete
     * : AJAX删除处理 idList=id / idList=id1,id3,id3
     *
     * @param request
     * @return 返回ajax结果
     * @throws @method
     */
    public AjaxResult delete(HttpServletRequest request) throws Exception {
        String idList = request.getParameter("idList");
        List<K> pks = new ArrayList<K>();
        // 批量删除
        if (idList.contains(",")) {
            String[] idTmpArr = idList.split(",");
            for (String id : idTmpArr) {
                K k = (K) ConvertUtils.convert(id, idClass);
                pks.add(k);
            }
        } else {// 单条数据删除
            K k = (K) ConvertUtils.convert(idList, idClass);
            pks.add(k);
        }
        String chkRes = checkContraints(pks, request);
        if (StringUtils.isNotEmpty(chkRes)) { // 检测数据存在外部引用
            return returnFailData(chkRes);
        }
        try {
            /*** 删除前读取数据 ****/
            if (pks.size() > 0) {
                if (loadDeleteDataForLog(request)) {
                    putDataForLog(pks);
                }
                service.deleteBatch(pks);
            }
            return returnSuccData(getLang("common_deleteSucess"), pks);
        } catch (Exception ex) {
            logger.error("{}", ex);
            String messege = getLang("common_deleteFail");
            Throwable able = ex.getCause();
            if (able != null) {
                String msg = able.getMessage();
                if (StringUtils.isNoneEmpty(msg)) {
                    if (messege.contains("ORA-02292")) {
                        messege = getLang("common_deleteRefFail");
                    }
                    messege = msg;
                }
            }
            return returnFailData(messege);
        }
    }

    /**
     * 是否需要提前删除前的数据，放入OperatorDataHolder，以便做日志记录
     *
     * @param request
     * @return
     */
    protected boolean loadDeleteDataForLog(HttpServletRequest request) {
        return false;
    }

    /**
     * 加载数据放入OperatorDataHolder为日志记录做好数据
     **/
    protected void putDataForLog(List<K> pks) throws Exception {
        List<T> list = new ArrayList<T>();
        for (K id : pks) {
            T obj = service.get(id);
            list.add(obj);
        }
        if (list.size() > 0) {
            OperatorDataHolder.setDataObject(list);
        }
    }

    /**
     * 时间格式化，支持：请使用 FastJsonFilterHolder 设置格式的定义,或者重写onFieldToJson
     * list
     * : AJAX查询datagrid数据，支持分页、多条件、排序查询
     *
     * @param request
     */
    public AjaxResult list(HttpServletRequest request) throws Exception {
        Map<String, Object> queryMap = this.getAllParamMapFromQuery(request, true);
        try {
            int page = Integer.parseInt(String.valueOf(request.getParameter("page")));
            int pageSize = Integer.parseInt(String.valueOf(request.getParameter("pageSize")));
            List<ClientButton> listBtns = new ArrayList<ClientButton>();
            DataGrid gridCfg = getDataGridCfg(request);
            if (gridCfg != null) {
                listBtns = gridCfg.getLineButton();
            }
            DynamicParameter dyParams = new DynamicParameter();
            dyParams.setPage(page);
            dyParams.setSize(pageSize);
            Map<String, Object> userParma = setListParams(request);
            LinkedHashMap<String, String> orderMap = setOrderBy(request, "");

            if (orderMap != null) {
                if (userParma.containsKey("orderColumn")) {
                    Set<Entry<String, String>> keySet = ((Map<String, String>) userParma.get("orderColumn")).entrySet();
                    for (Entry<String, String> entry : keySet) {
                        String key = entry.getKey();
                        if (!orderMap.containsKey(key)) {
                            orderMap.put(key, entry.getValue());
                        }
                    }
                }
                dyParams.setOrderMap(orderMap);
                userParma.remove("orderColumn");
            } else if (userParma.containsKey("orderColumn")) {
                dyParams.setOrderMap((LinkedHashMap<String, String>) userParma.get("orderColumn"));
                userParma.remove("orderColumn");
            }
            for (Entry<String, Object> entry : queryMap.entrySet()) {
                if (!userParma.containsKey(entry.getKey())) {
                    userParma.put(entry.getKey(), entry.getValue());
                }
            }
            dyParams.setParams(userParma);
            PagingResult<T> pgResult = exePaginQuery(dyParams);
            beforeListReturn(pgResult, request);
            JSONObject tmpObj = pagingResultToJson(pgResult, request, listBtns);
            setGridHeader(gridCfg, tmpObj, request);
            return returnSuccData(getLang("common_querySucess"), tmpObj, false);

        } catch (Exception e) {
            logger.error("list data fail: {}", e);
            throw e;
        }
    }

    protected PagingResult<T> exePaginQuery(DynamicParameter dyParams) throws Exception {
        PagingResult<T> pgResult = service.selectPagination(dyParams);
        return pgResult;
    }


    /***
     *  分页结果转json
     */
    protected <E> JSONObject pagingResultToJsonE(PagingResult<E> pgResult, HttpServletRequest request,
                                                 List<ClientButton> listBtns, Class<E> beanClass, IControlCommon commonImp) throws IllegalAccessException, InvocationTargetException, Exception {
        JSONObject tmpObj = pgResult.toJSONObject(request, beanClass, setExcludeFields(request), commonImp, listBtns);
        return tmpObj;
    }

    /***
     *  分页结果转json
     */
    protected JSONObject pagingResultToJson(PagingResult<T> pgResult, HttpServletRequest request,
                                            List<ClientButton> listBtns) throws IllegalAccessException, InvocationTargetException, Exception {
        JSONObject tmpObj = pgResult.toJSONObject(request, entityClass, setExcludeFields(request), this, listBtns);
        return tmpObj;
    }

    @Override
    public Object onFieldToJson(T obj, String fieldName, JSONObject jsonBean) {
        // TODO Auto-generated method stub
        return null;
    }

    /**
     * Restful API 根据id查询返回数据
     *
     * @param id-数据id
     * @return
     * @throws Exception-
     */
    public AjaxResult get(String id) throws Exception {
        K k = (K) ConvertUtils.convert(id, idClass);
        T obj = service.get(k);
        return returnSuccData("", obj);
    }

    /**
     * : AJAX查询数据，与JSON格式返回
     */
    public AjaxResult query(HttpServletRequest request) throws Exception {
        Map<String, Object> paramMap = setQueryParams(request);
        List<T> list = service.selectParam(paramMap);
        return returnSuccData("", list);
    }


    /**
     * Restful API 根据条件count数据是否存在
     *
     * @param request -数据id
     * @return
     * @throws Exception-
     */
    public AjaxResult count(HttpServletRequest request) throws Exception {
        DynamicCountParam countParam = this.setDynamicCountParams(request);
        if (countParam == null) {
            throw new Exception("please override [setDynamicCountParams] !");
        }
        int count = this.service.countByDynamicParams(countParam);
        return returnSuccData("", count);
    }

    /**
     * count接口采用动态dao，需要重写返回相关参数
     *
     * @param request
     * @return
     */
    public DynamicCountParam setDynamicCountParams(HttpServletRequest request) {
        return null;
    }


    /**
     * upload
     * : 附件上传
     *
     * @param request
     * @param response
     * @method 0010107
     */
    public void upload(HttpServletRequest request, HttpServletResponse response) throws Exception {
        AjaxResult result = new AjaxResult(0, "");
        if (ServletFileUpload.isMultipartContent(request)) {// 判断表单中是否存在文件
            MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request;
            Map<String, List<MultipartFile>> fileMap = AdminControllerHelper.getMultipartFile(request);
            Map<String, String> jsonResultData = new HashMap<String, String>();
            boolean ok = saveFiles(multipartRequest, fileMap, jsonResultData);
            Set<Entry<String, String>> setsEntries = jsonResultData.entrySet();
            JSONObject jobj = new JSONObject();
            for (Entry<String, String> entry : setsEntries) {
                jobj.put(entry.getKey(), entry.getValue());
            }
            result.data = jobj;
            if (ok) {
                result.code = 0;
            } else {
                result.code = 1;
                if (logger.isDebugEnabled()) {
                    logger.debug("upload file fail");
                }
            }
        } else {
            result.code = 1;
            if (logger.isDebugEnabled()) {
                logger.debug("upload no file is found");
            }
        }
        response(response, result);
    }

    /**
     * : 将Ajax结果利用response返回
     */
    protected void response(HttpServletResponse response, AjaxResult result) throws IOException {
        response.reset();
        response.setCharacterEncoding("utf-8");
        response.setContentType("text/html");
        OutputStream out = response.getOutputStream();
        out.write(JSONObject.toJSONString(result).getBytes("utf-8"));
        out.close();
    }

    /**
     * : 子类重写实现文件保存即可
     *
     * @param request-请求对象
     * @param fileMap-文件集合
     * @param uploadResult-处理的信息结果
     * @return @throws
     */
    public boolean saveFiles(MultipartHttpServletRequest request, Map<String, List<MultipartFile>> fileMap, Map<String, String> uploadResult) {
        for (Entry<String, List<MultipartFile>> entry : fileMap.entrySet()) {
            StringBuffer buffer = new StringBuffer();
            List<MultipartFile> list = entry.getValue();
            int len = list.size() - 1;
            int help = 0;
            for (MultipartFile file : entry.getValue()) {
                buffer.append(file.getName());
                if (help < len) {
                    buffer.append(";");
                }
            }
            uploadResult.put(entry.getKey(), buffer.toString());
        }
        return true;
    }

    /**
     * : 将需要删除的文件全路径方式到定时任务里面，定时任务会执行删除临时文件
     *
     * @param path-需要删除的文件全路径
     */
    public void putTmpFileToDelete(String path) {
        ClearTempFileTimer.putFilePath(path);
    }

    /**
     * :获取应用物理根目录
     **/
    public String getContextDirPath(HttpServletRequest request) {
        return request.getServletContext().getRealPath("/");
    }

    /**
     * :获取应用物理根目录下的子目录
     **/
    public String getContextDirPath(HttpServletRequest request, String subDir) {
        return request.getServletContext().getRealPath("/" + subDir);
    }


    /**
     * :用于子类重写返回query查询的参数 ，默认无参数，返回null
     */
    public Map<String, Object> setQueryParams(HttpServletRequest request) {

        return null;
    }

    /***
     * :不需要转为json的字段集合
     ***/
    public Set<String> setExcludeFields(HttpServletRequest request) throws Exception {
        return null;
    }

    /***
     * :设置排序字段，如 orderMap.put("createTime","asc")支持多字段排队_col_sort_fieldName
     ***/
    public LinkedHashMap<String, String> setOrderBy(HttpServletRequest request, String tablePrefix) {
        LinkedHashMap<String, String> pre = new LinkedHashMap<String, String>();
        Map<String, String[]> prMap = request.getParameterMap();
        String expString = "(?<=[a-z])(?=[A-Z])|(?<=[A-Z])(?=[A-Z][a-z])";
        String sortString = "_col_sort_";
        for (Entry<String, String[]> entry : prMap.entrySet()) {
            String key = entry.getKey();
            if (key.contains(sortString)) {
                String keyString = key.replace(sortString, "");
                String[] tmpArray = keyString.split(expString);//按大写拆分
                if (tmpArray.length > 1) {
                    StringBuffer buffer = new StringBuffer();
                    for (int i = 0, len = tmpArray.length; i < len; ++i) {
                        buffer.append(tmpArray[i]);
                        if (i < len - 1) {
                            buffer.append("_");
                        }
                    }
                    keyString = buffer.toString();
                }
                if (StringUtils.isNotEmpty(tablePrefix)) {
                    keyString = tablePrefix + "." + keyString;
                }
                pre.put(keyString, entry.getValue()[0]);
            }
        }
        return pre;
    }

    /***
     * :设置分页查询参数
     ***/
    protected Map<String, Object> setListParams(HttpServletRequest request) throws Exception {
        return new HashMap<String, Object>();
    }

    /***
     * :设置datagrid的表头，一般用于实现动态表头
     ****/
    protected void setGridHeader(DataGrid gridCfg, JSONObject tmpObj, HttpServletRequest request) {

    }

    /**
     * : 返回前的重写处理
     *
     * @param pgResult
     */
    protected void beforeListReturn(PagingResult<T> pgResult, HttpServletRequest request) {

    }

    /**
     * :从request中提取除分页参数外的所有参数【_sort$_、gridid、pageSize、page、_diff_除外】
     **/
    public Map<String, Object> getAllParamMapFromQuery(HttpServletRequest request, boolean urlDecode)
            throws UnsupportedEncodingException {
        Map<String, Object> map = new HashMap<String, Object>();
        Map<String, String[]> prMap = request.getParameterMap();
        for (Entry<String, String[]> entry : prMap.entrySet()) {
            String key = entry.getKey();
            if (key.contains("_sort$_") || key.equals("_diff_") || "gridid".equals(key) || "pageSize".equals(key)
                    || "page".equals(key)) {
                continue;
            }
            String[] values = entry.getValue();
            if (values.length > 0) {
                String v = values[0];
                if (StringUtils.isNotEmpty(v)) {
                    if (urlDecode) {
                        map.put(key, URLDecoder.decode(v, "utf-8"));
                    } else {
                        map.put(key, v);
                    }
                }
            }
        }
        return map;
    }

    /**
     * : 检查数据约束情况
     *
     * @param: pks id列表
     */
    protected String checkContraints(List<K> pks, HttpServletRequest request) throws Exception {
        /*
         * Map<String, Object> list = new HashMap<String, Object>(); list.put("keys",
         * pks); List<String> langKeys = this.service.checkContraints(list);
         * if(langKeys.size()>0){ //检测数据存在外部引用 StringBuffer msg=new StringBuffer();
         * for(String key : langKeys){ msg.append(getLabel(key)); msg.append("<br/>"); }
         * return msg.toString(); }
         */
        return null;
    }

    /*** :根据key获取语言 value *****/
    /*** :根据key获取语言 value *****/
    public String getLang(String key) {
        String lang = "";
        try {
            ILoginUserContext userContext = getLoginUserCtx();
            if (userContext != null) {
                LoginUser user = userContext.getCurrentUser();
                if (user != null) {
                    lang = user.getLang();
                }
            }
        } catch (Exception e) {
            logger.warn("", e);
        }
        if (StringUtils.isEmpty(lang) && StringUtils.isNotEmpty(SysConfigParams.lang)) {
            lang = SysConfigParams.lang;
        } else {
            lang = "zh";
        }
        LanguageMap map = languageMap.get(lang);
        if (map == null) {
            return "";
        }
        return map.getLangByKey(key);
    }

    /**
     * 时间格式化，支持：请使用 FastJsonFilterHolder 设置格式的定义
     * : 返回数据
     *
     * @return AjaxResult
     * @param: code-0表示成功，1表示失败
     * @param: message--提示信息
     * @param: data--附带的数据
     * @param: strConvert是否需要客户端JSON转换
     */
    public AjaxResult returnData(int code, String message, Object data, boolean strConvert) {
        AjaxResult result = new AjaxResult(code, message, data, strConvert);
        return result;
    }

    /**
     * 时间格式化，支持：请使用 FastJsonFilterHolder 设置格式的定义
     * : 成功返回
     *
     * @param message-信息
     * @param data-数据
     * @param strConvert-是否需要客户端JSON转换
     * @return AjaxResult
     */
    public AjaxResult returnSuccData(String message, Object data, boolean strConvert) {
        return this.returnData(0, message, data, strConvert);
    }

    /**
     * 时间格式化，支持：请使用 FastJsonFilterHolder 设置格式的定义
     * :成功返回
     *
     * @param message-信息
     * @param data-数据
     * @return AjaxResult
     */
    public AjaxResult returnSuccData(String message, Object data) {
        return this.returnSuccData(message, data, false);
    }

    /**
     * 时间格式化，支持：请使用 FastJsonFilterHolder 设置格式的定义
     * :成功返回
     *
     * @param data-数据
     * @return AjaxResult
     */
    public AjaxResult returnSuccData(Object data) {
        return this.returnSuccData(getLang("common_operatorSuccess"), data, false);
    }

    /**
     * 时间格式化，支持：请使用 FastJsonFilterHolder 设置格式的定义
     * : 成功返回
     *
     * @return AjaxResult
     */
    public AjaxResult returnSuccess() {
        return this.returnSuccData(getLang("common_operatorSuccess"), null);
    }

    /**
     * 时间格式化，支持：请使用 FastJsonFilterHolder 设置格式的定义
     * :成功返回
     *
     * @param message-信息
     * @return AjaxResult
     */
    public AjaxResult returnSuccMsg(String message) {
        return this.returnSuccData(message, null);
    }

    /**
     * 时间格式化，支持：请使用 FastJsonFilterHolder 设置格式的定义
     * : 返回失败结果
     *
     * @param message-信息
     * @return AjaxResult
     */
    public AjaxResult returnFailData(String message) {
        return this.returnFailData(message, null, false);
    }

    /**
     * 时间格式化，支持：请使用 FastJsonFilterHolder 设置格式的定义
     * :返回失败结果
     *
     * @param message-信息
     * @param data-数据
     * @return AjaxResult
     */
    public AjaxResult returnFailData(String message, Object data) {
        return this.returnFailData(message, data, false);
    }

    /**
     * 时间格式化，支持：请使用 FastJsonFilterHolder 设置格式的定义
     * :返回失败结果
     *
     * @param message-信息
     * @param data-数据
     * @param strConvert-是否需要客户端json转换
     * @return AjaxResult
     */
    public AjaxResult returnFailData(String message, Object data, boolean strConvert) {
        return this.returnData(1, message, data, strConvert);
    }

    /**
     * : 新增/更新保存前的过滤操作 ,在此嵌入验证
     *
     * @param bean-实体bean
     * @param isupdate-是更新、或者新增
     * @return 返回空字符串信息则执行保存，否则不执行保存，并且返回信息发给客户端
     */
    public String saveFilter(T bean, boolean isupdate, HttpServletRequest request) {
        boolean isSkip = StringUtils.isNotEmpty(request.getParameter("__skipSaveFilter"));
        if (isSkip) {
            return "";
        }
        HashSet<String> excFields = new HashSet<String>();
        if (isupdate) {
            // 更新情况下，需要检查是否存在新旧值校验
            Field[] fields = entityClass.getDeclaredFields();
            for (Field f : fields) {
                String pName = f.getName();
                NewOldCompare noCompare = f.getAnnotation(NewOldCompare.class);
                if (noCompare != null) {
                    String newValue = request.getParameter(pName);
                    String tmpName = "old_" + pName;
                    String oldValue = request.getParameter(tmpName);
                    if (oldValue == null) {// 读取数据库检查字段值是否已经修改
                        K beanId = null;
                        try {
                            if (getIdMethod == null) {
                                getIdMethod = entityClass.getMethod("getId");
                                getIdMethod.setAccessible(true);
                            }
                            beanId = (K) (getIdMethod.invoke(bean));
                        } catch (Exception e) {
                            return getLang("common_newOldCompare_excption").replace("field", pName);
                        }
                        if (beanId != null) {
                            try {
                                Map<String, Object> param = new HashMap<String, Object>();

                                LinkedList<WhereField> list = WhereField.getWhereFieldList();
                                list.add(new WhereField("", "id", "=", beanId));

                                List<String> selectFields = new ArrayList<String>();
                                selectFields.add(WhereField.beanName2FieldNameForSelect(pName));

                                param.put(SysConstants.sqlSelectFieldsKey, selectFields);
                                param.put(SysConstants.sqlwhereKey, list);

                                List<T> resList = this.service.selectOnfield(param);
                                if (resList.size() > 0) {
                                    T dbBean = resList.get(0);
                                    String filedName = pName.substring(0, 1).toUpperCase() + pName.substring(1);
                                    Method getMethod = entityClass.getMethod("get" + filedName);
                                    getMethod.setAccessible(true);
                                    oldValue = String.valueOf(getMethod.invoke(dbBean));
                                } else {
                                    oldValue = newValue;
                                }
                            } catch (Exception e) {
                                return getLang("common_newOldCompare_excption").replace("field", pName);
                            }
                        }
                    }
                    if (newValue.equals(oldValue)) {// 新旧相等则排除验证
                        excFields.add(pName);
                    }
                }
            }
        }
        return AdminControllerHelper.validEntityBean(bean, excFields, this, request);
    }

    /**
     * : 从当前请求中获取登陆用户的数据
     */
    protected LoginUser getLoginUser() {
        try {
            LoginUser u = getLoginUserCtx().getCurrentUser();
            return u;
        } catch (Exception e) {
            logger.info("LoginUser is null !!!!!!!!!!!!!!!!!!!!!!!!!!!");
            return null;
        }
    }

    /**
     * : 子类重写该方法，读取更新后的数据放到更新操作结果里以便客户端使用更新后的数据
     *
     * @return 默认返回实体JSON
     */
    protected Object setAnUResult(T t) throws Exception {
        return JSONObject.toJSON(t);
    }

    /***
     * :更新情况下设置实体的json到request的entityJson中
     ***/
    protected void setUpdateObjectJson(HttpServletRequest request) throws Exception {
        String id = request.getParameter("id");
        if (StringUtils.isNotEmpty(id)) {
            @SuppressWarnings("unchecked")
            K k = (K) ConvertUtils.convert(id, idClass);
            T obj = service.get(k);
            String json = JSONObject.toJSONString(obj, setJsonDateSerialize(),
                    SerializerFeature.DisableCircularReferenceDetect);
            request.setAttribute("entityJson", json);
        } else {
            id = "";
            request.setAttribute("entityJson", "{}");
        }
        request.setAttribute("id", id);
    }

    /*** list-列表 -tojson时候设置时间日期的格式化 ***/
    protected SerializeConfig setJsonDateSerialize() {
        return dateTimeSerialize;
    }

    /**
     * :带时间格式的json转换
     **/
    protected String toJSONStringByDateFormate(Object bean) {
        String json = JSONObject.toJSONString(bean, setJsonDateSerialize(),
                SerializerFeature.DisableCircularReferenceDetect);
        return json;
    }

    /***
     * :可以重写从子类本身的静态变量取值
     ***/
    public DataGrid getDataGridCfg(HttpServletRequest request) {
        DataGrid dg = null;
        String gridid = request.getParameter("gridid");
        if (gridid == null) {
            Object _gridid = request.getAttribute("gridid");
            if (_gridid != null) {
                gridid = String.valueOf(_gridid);
            }
        }
        return getDataGridCfg(gridid, request);
    }

    /***
     * 一个datagrid文件 配置多个datagrid时候，请一定要重写getDataGridFilePreName，返回文件前部分名称
     * ****/
    public DataGrid getDataGridCfg(String gridid, HttpServletRequest request) {
        DataGrid dg = null;
        String filePreName = getDataGridFilePreName(request);
        if (gridid != null) {
            try {
                try {
                    dg = DataGridHelper.getDataGridCfg(setGridModelPath(request), filePreName, gridid);
                } catch (Throwable e) {
                    logger.error("getDataGridCfg:{}", e);
                }
            } catch (Throwable e) {
                logger.error("getDataGridCfg:{}", e);
            }
        }
        return dg;
    }

    /**
     * 设置datagrid配置的模块路径，默认为configHome/datagrid/base return "base/";
     ***/
    public String setGridModelPath(HttpServletRequest request) {
        return "base/";
    }

    /**
     * 获取datagrid配置文件的前缀名称，默认返回null则以gridid参数为文件前缀
     ***/
    protected String getDataGridFilePreName(HttpServletRequest request) {
        return null;
    }

    /**
     * 设置页面的模块路径，不设置的情况下，默认为WEB-INF/pages/路径下的实体bean名称
     ***/
    public String setPageModelPath(HttpServletRequest request) {
        return entityPath; // 实体bean名称作为模块文件夹名称
    }

    /***在应用根目录下创建 dirName目录，不需要/开头拼接
     * @param dirName
     * @param request
     * @return 返回的路径 不以 / 结束
     */
    public String createDir(String dirName, HttpServletRequest request) {
        return AdminControllerHelper.createDir(dirName, request);
    }

    @Override
    public boolean serviceValid(Map<String, Object> params) throws Exception {
        return service.uniqueValid(params);
    }

    @Override
    public void extGridResult(T bean, JSONObject jsonObj) throws Exception {
        // TODO Auto-generated method stub

    }

    /**
     * 数据权限，可以根据数据bean来控制按钮的权限 默认走 hasPrivilage(request,cmd)
     ***/
    @Override
    public boolean hasDataPrivilage(T bean, HttpServletRequest request, String cmd) {
        return hasPrivilage(request, cmd);
    }

    /**
     * 按钮权限UI控制逻辑
     ***/
    @Override
    public boolean hasPrivilage(HttpServletRequest request, String cmd) {
        LoginUser user = getLoginUser();
        if (user == null) {
            return false;
        }
        if (user.isSuperAdmin()) {
            return true;
        }
        boolean pri = false;
        UrlInfo info = AdminControllerHelper.getControllerAndCmd(request);
        if (SysConfigParams.isOpenApi(info.getController(), info.getCmd())) {
            return true;
        }
        if (SysConfigParams.canAccess(info.getController(), info.getCmd())) {
            return true;
        }
        Map<String, List<UserFunc>> authMap = user.getAuthMap();
        String authKey = info.getAuthController();
        if (StringUtils.isEmpty(cmd)) {
            cmd = info.getCmd();
        }
        List<UserFunc> cmdList = authMap.get(authKey);
        for (UserFunc f : cmdList) {
            if (f.getFuncCode().equals(cmd)) {
                pri = true;
                break;
            }
        }
        return pri;
    }

    /**
     * 注意，当拦截的是列表头部工具栏时候，bean为null，请注意做好判断
     ***/
    @Override
    public void buttonCreateHanlder(T bean, ClientButton button) {
        // TODO Auto-generated method stub
    }

    /**
     * 获取服务service bean
     ***/
    protected Object getBean(String beanName) {
        try {
            return SpringContextUtil.getBean(beanName);
        } catch (Exception ex) {
            if (!beanName.equals("loginUserCtx")) {
                logger.error("{}", ex);
            }
        }
        return null;
    }


    protected void setDownLoadFlag(HttpServletRequest request) throws Exception {
        AdminControllerHelper.setDownLoadFlag(request, loginUserCtx);
    }

    protected void clearDownLoadFlag(HttpServletRequest request) throws Exception {
        AdminControllerHelper.clearDownLoadFlag(request, loginUserCtx);
    }

    @RequestMapping("checkresponse")
    public @ResponseBody
    AjaxResult checkresponse(HttpServletRequest request, HttpServletResponse response) throws Throwable {
        return AdminControllerHelper.checkresponse(loginUserCtx, request);
    }
}
